package com.mindskip.xzs.configuration.spring.security;
//前端： 在用户登录时，前端会将用户输入的用户名和密码封装成一个Authentication对象，并调用该自定义认证提供者的authenticate方法进行用户认证。
//后端： 该自定义认证提供者会通过构造函数注入认证服务（AuthenticationService）和用户服务（UserService），然后在authenticate方法中完成用户认证的逻辑，具体包括：
//从Authentication对象中获取用户名和密码；
//根据用户名从数据库中获取用户信息；
//调用认证服务进行用户认证；
//检查用户状态，如用户被禁用等；
//创建Spring Security的User对象，并将用户角色权限添加到权限列表中；
//返回认证成功的Authentication对象。
//作用： 该自定义认证提供者在整个认证流程中起到了关键作用，负责实际的用户认证逻辑，包括从数据库中获取用户信息、验证用户身份和密码、检查用户状态等。
// 通过实现supports方法，判断该认证提供者是否支持指定的认证类型。最终返回认证成功的Authentication对象，以供Spring Security进行后续的授权操作。
import com.mindskip.xzs.domain.enums.RoleEnum;
import com.mindskip.xzs.domain.enums.UserStatusEnum;
import com.mindskip.xzs.service.AuthenticationService;
import com.mindskip.xzs.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;

// 使用@Component注解将这个类声明为一个Spring组件
@Component
// 自定义认证提供者类，实现AuthenticationProvider接口
public class RestAuthenticationProvider implements AuthenticationProvider {

    // 注入自定义的AuthenticationService和UserService
    private final AuthenticationService authenticationService;
    private final UserService userService;

    // 使用@Autowired注解通过构造函数注入依赖
    @Autowired
    public RestAuthenticationProvider(AuthenticationService authenticationService, UserService userService) {
        this.authenticationService = authenticationService;
        this.userService = userService;
    }

    // 实现authenticate方法，用于进行认证逻辑
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 从Authentication对象中获取用户名和密码
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();

        // 根据用户名从数据库中获取用户信息
        com.mindskip.xzs.domain.User user = userService.getUserByUserName(username);
        if (user == null) {
            // 如果用户不存在，抛出用户名未找到异常
            throw new UsernameNotFoundException("用户名或密码错误");
        }

        // 调用自定义的认证服务进行用户认证
        boolean result = authenticationService.authUser(user, username, password);
        if (!result) {
            // 如果认证失败，抛出凭证错误异常
            throw new BadCredentialsException("用户名或密码错误");
        }

        // 检查用户状态，如果用户被禁用，抛出账户锁定异常
        UserStatusEnum userStatusEnum = UserStatusEnum.fromCode(user.getStatus());
        if (UserStatusEnum.Disable == userStatusEnum) {
            throw new LockedException("用户被禁用");
        }

        // 创建一个权限列表，并添加用户的角色权限
        ArrayList<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        grantedAuthorities.add(new SimpleGrantedAuthority(RoleEnum.fromCode(user.getRole()).getRoleName()));

        // 创建Spring Security的User对象
        User authUser = new User(user.getUserName(), user.getPassword(), grantedAuthorities);
        // 返回认证成功的Authentication对象
        return new UsernamePasswordAuthenticationToken(authUser, authUser.getPassword(), authUser.getAuthorities());
    }

    // 实现supports方法，判断AuthenticationProvider是否支持指定的认证类型
    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
